package com.mx.spring.dev.result;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.mx.spring.dev.code.Code;
import com.mx.spring.dev.code.ICode;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @Author: mengxiang.
 * @create: 2021-07-02 16:58
 * @Description: 通用请求返回数据-操作消息提醒
 */
@ApiModel(value = "MxResult", description = "通用请求返回数据-操作消息提醒")
public class MxResult<T> implements Serializable {

    @ApiModelProperty(value = "错误码")
    private String code;

    @ApiModelProperty(value = "错误信息")
    private String msg;

    @ApiModelProperty(value = "返回数据")
    private T data;

    private Map<String, Object> attrs = new HashMap<>();

    public MxResult(String code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public MxResult() {
    }

    public Map<String, Object> attrs() {
        return attrs;
    }

    @SuppressWarnings("unchecked")
    public <M> M attr(String attrKey) {
        return (M) this.attrs.get(attrKey);
    }

    public MxResult<T> attr(String attrKey, Object attrValue) {
        this.attrs.put(attrKey, attrValue);
        return this;
    }


    public MxResult<T> data(Object attrValue) {
        this.attrs.put("data", attrValue);
        return this;
    }

    public MxResult<T> attr(String attrKey, Object attrValue, Object defaultValue) {
        this.attrs.put(attrKey, ObjectUtils.defaultIfNull(attrValue, defaultValue));
        return this;
    }

    public MxResult<T> attrs(Map<String, Object> attrs) {
        this.attrs = attrs;
        return this;
    }

    public static <T> boolean check(MxResult<T> result) {
        return Code.SUCCESS.code().equals(result.code);
    }

    public boolean check() {
        return Code.SUCCESS.code().equals(this.code);
    }

    /**
     * 根据参数返回成功还是失败
     */
    public static <T> MxResult<T> result(Object object) {
        if (object != null) {
            return MxResult.ok();
        }
        return MxResult.fail();
    }

    /**
     * 根据参数返回成功还是失败
     */
    public static <T> MxResult<T> result(int result) {
        if (result >= 1) {
            return MxResult.ok();
        }
        return MxResult.fail();
    }

    /**
     * 根据参数返回成功还是失败
     */
    public static <T> MxResult<T> result(List<?> list) {
        if (CollectionUtil.isNotEmpty(list)) {
            return MxResult.ok();
        }
        return MxResult.fail();
    }

    /**
     * 根据参数返回成功还是失败
     */
    public static <T> MxResult<T> result(int[] result) {
        if (result != null && result.length > 0) {
            return MxResult.ok();
        }
        return MxResult.fail();
    }

    /**
     * 成功result
     */
    public static <T> MxResult<T> ok() {
        return MxResult.create(Code.SUCCESS);
    }

    /**
     * 成功result
     */
    public static <T> MxResult<T> ok(T data) {
        return MxResult.create(Code.SUCCESS, data);
    }


    /**
     * 失败result
     */
    public static <T> MxResult<T> fail() {
        return MxResult.create(Code.ERROR);
    }

    public static <T> MxResult<T> create(ICode iCode) {
        return create(iCode, null);
    }

    public static <T> MxResult<T> create(ICode iCode, T data) {
        return new MxResult<>(iCode.code(), iCode.msg(), data);
    }

    public static <T> MxResult<T> create(String code, String msg) {
        return create(code, msg, null);
    }

    public static <T> MxResult<T> create(String code, String msg, T data) {
        return new MxResult<>(code, msg, data);
    }


    public static <T> MxResult<T> sameName() {
        return MxResult.create(Code.FIELDS_EXISTS.code(), StrUtil.format(Code.FIELDS_EXISTS.msg(), "名称"));
    }

    public static <T> MxResult<T> sameData(String msg) {
        return MxResult.create(Code.FIELDS_EXISTS.code(), StrUtil.format(Code.FIELDS_EXISTS.msg(), msg));
    }

    public static <T> MxResult<T> noVersion() {
        return MxResult.create(Code.VERSION_NOT_SAME);
    }

    public static <T> MxResult<T> noData() {
        return MxResult.create(Code.NO_DATA);
    }

    public static <T> MxResult<T> noLogin() {
        return MxResult.create(Code.NOT_LOGIN);
    }

    public static boolean checkVersion(Object var1, Object var2) {
        return Objects.equals(var1, var2);
    }


    public String code() {
        return code;
    }

    public String msg() {
        return StringUtils.trimToEmpty(msg);
    }

    public String toJson() {
        return JSONObject.toJSONString(this, SerializerFeature.PrettyFormat);
    }

    public T data() {
        return this.data;
    }


    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public Map<String, Object> getAttrs() {
        return attrs;
    }

    public void setAttrs(Map<String, Object> attrs) {
        this.attrs = attrs;
    }
}
